package com.demo.chapter11future.asyncadddiscount;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.stream.Stream;

import com.demo.chapter11future.sync.Shop;

public class Demo4 {

	//两个CompletionStage，谁计算的快，我就用那个CompletionStage的结果进行下一步的转化操作。
	//我们现实开发场景中，总会碰到有两种渠道完成同一个事情，所以就可以调用这个方法，找一个最快的结果进行处理。
	public static void applyToEither() {
		String result = CompletableFuture.supplyAsync(() -> {
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return "s1";
		}).applyToEither(CompletableFuture.supplyAsync(() -> {
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return "hello world";
		}), s -> s).join();
		System.out.println(result);
	}

	//两个CompletionStage，谁计算的快，我就用那个CompletionStage的结果进行下一步的消耗操作。
	public static void acceptEither() {
		CompletableFuture.supplyAsync(() -> {
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return "s1";
		}).acceptEither(CompletableFuture.supplyAsync(() -> {
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return "hello world";
		}), System.out::println);
		try {
			Thread.sleep(4000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	//两个CompletionStage，任何一个完成了都会执行下一步的操作（Runnable）。
	public static void runAfterEither() {
		CompletableFuture.supplyAsync(() -> {
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return "s1";
		}).runAfterEither(CompletableFuture.supplyAsync(() -> {
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return "s2";
		}), () -> System.out.println("hello world"));
		try {
			Thread.sleep(4000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	//当运行时出现了异常，可以通过exceptionally进行补偿。
	public static void exceptionally() {
		String result = CompletableFuture.supplyAsync(() -> {
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			if (1 == 1) {
				throw new RuntimeException("测试一下异常情况");
			}
			return "s1";
		}).exceptionally(e -> {
			System.out.println(e.getMessage());
			return "hello world";
		}).join();
		System.out.println(result);
	}

	//当运行完成时，对结果的记录。这里的完成时有两种情况，一种是正常执行，返回值。另外一种是遇到异常抛出造成程序的中断。这里为什么要说成记录，
	//因为这几个方法都会返回CompletableFuture，当Action执行完毕后它的结果返回原始的CompletableFuture的计算结果或者返回异常。所以不会对结果产生任何的作用。
	public static void whenComplete() {
		String result = CompletableFuture.supplyAsync(() -> {
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return "s1";
		}).whenComplete((s, t) -> {
			System.out.println(s);
		}).join();
		System.out.println("result = " + result);
	}
	//这里也可以看出，如果使用了exceptionally，就会对最终的结果产生影响，它没有口子返回如果没有异常时的正确的值，这也就引出下面我们要介绍的handle。
	public static void whenComplete2() {
		String result = CompletableFuture.supplyAsync(() -> {
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			if (1 == 1) {
				throw new RuntimeException("测试一下异常情况");
			}
			return "s1";
		}).whenComplete((s, t) -> {
			System.out.println(s);
			System.out.println(t.getMessage());
		}).exceptionally(e -> {
			System.out.println(e.getMessage());
			return "hello world";
		}).join();
		System.out.println("result = " + result);
	}

	//运行完成时，对结果的处理。这里的完成时有两种情况，一种是正常执行，返回值。另外一种是遇到异常抛出造成程序的中断。
	//出现异常时
	public static void handle() {
	    String result = CompletableFuture.supplyAsync(() -> {
	        try {
	            Thread.sleep(3000);
	        } catch (InterruptedException e) {
	            e.printStackTrace();
	        }
	        //出现异常
	        if (1 == 1) {
	            throw new RuntimeException("测试一下异常情况");
	        }
	        return "s1";
	    }).handle((s, t) -> {
	        if (t != null) {
	            return "hello world";
	        }
	        return s;
	    }).join();
	    System.out.println(result);
	}
	//未出现异常时
	public static void handle2() {
		String result = CompletableFuture.supplyAsync(() -> {
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return "s1";
		}).handle((s, t) -> {
			if (t != null) {
				return "hello world";
			}
			return s;
		}).join();
		System.out.println(result);
	}

	public static void main(String[] args) {
		//applyToEither();
		//acceptEither();
		//runAfterEither();
		//exceptionally();
		whenComplete();
		handle();
		handle2();
	}

}
